package utils

import (
	"time"

	"github.com/golang-jwt/jwt/v4"
)

var jwtSecretKey = []byte("hankex123")

type Claims struct {
	Id       uint   `json:"id"`
	UserName string `json:"user_name"`
	jwt.RegisteredClaims
}

// 签发用户 token
func GenerateToken(id uint, userName string) (string, error) {
	timeNow := time.Now()
	claims := Claims{
		Id:       id,
		UserName: userName,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(timeNow.Add(4 * time.Hour)),
			NotBefore: jwt.NewNumericDate(timeNow),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	ss, err := token.SignedString(jwtSecretKey)
	return ss, err
}

// 验证用户 token
func ParseToken(tokenStr string) (*Claims, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &Claims{}, func(t *jwt.Token) (interface{}, error) {
		return jwtSecretKey, nil
	})
	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	} else {
		return nil, err
	}
}

type EmailClaims struct {
	OperationType uint   `json:"operation_type"`
	UserName      string `json:"user_name"`
	NickName      string `json:"nick_name"`
	Email         string `json:"email"`
	Password      string `json:"password"`
	jwt.RegisteredClaims
}

// 生成邮箱 token
func GenerateEmailToken(operation uint, userName, nickName, email, password string) (string, error) {
	timeNow := time.Now()
	claims := EmailClaims{
		OperationType: operation, // 1.用户激活 2.解绑邮箱 3.绑定邮箱 4.更改密码
		UserName:      userName,
		NickName:      nickName,
		Email:         email,
		Password:      password,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(timeNow.Add(time.Hour * 48)),
			NotBefore: jwt.NewNumericDate(timeNow),
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	ss, err := token.SignedString(jwtSecretKey)
	return ss, err
}

// 验证用户邮箱 token
func ParseEmailToken(tokenStr string) (*EmailClaims, error) {
	token, err := jwt.ParseWithClaims(tokenStr, &EmailClaims{}, func(t *jwt.Token) (interface{}, error) {
		return jwtSecretKey, nil
	})
	if claims, ok := token.Claims.(*EmailClaims); ok && token.Valid {
		return claims, nil
	}
	return nil, err
}
